<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<script>
// TODO: 总结:
// 区分创建的还是继承的
// 继承: subClass extends superClass
    // subClass.__proto__ 指向 superClass
    // subClass.prototype.__proto__ 指向 superClass.prototype
// 新建: 针对于 object
    // xialuo 是 Student new 出来的, 则 xialuo 的 __proto__ 指向 Student 的 prototype
    // Function.prototype / People.prototype 是 Object new 出来的, 则 People.prototype / Function.prototype 的 __proto__ 指向 Object.prototype
    // Object / Function / People 是 Function new 出来的, 则 Object / Function / People 的 __proto__ 指向 Function 的 prototype



// 父类
class People {
    constructor(name) {
        this.name = name;
    }
    eat() {
        console.log(`${this.name} eat something`);
    }
}

// 子类
class Student extends People {
    constructor(name, number) {
        super(name); // 调用父类的构造函数
        this.number = number;
    }
    sayHi() {
        console.log(`姓名 ${this.name} 学号 ${this.number}`);
    }
}

// 子类
class Teacher extends People {
    constructor(name, major) {
        super(name);
        this.major = major;
    }
    teach() {
        console.log(`${this.name} 教授 ${this.major}`);
    }
}

// 实例
const xialuo = new Student('夏洛', 100);
console.log(xialuo.name);
console.log(xialuo.number);
xialuo.sayHi();
xialuo.eat();

// 实例
const wanglaoshi = new Teacher('王老师', '语文');
console.log(wanglaoshi.name);
console.log(wanglaoshi.major);
wanglaoshi.teach();
wanglaoshi.eat();

// TODO:类型判断
xialuo instanceof Student; // true
xialuo instanceof People; // true
xialuo instanceof Object; // true
[] instanceof Array; // true
[] instanceof Object; // true
// {} instanceof Object; // true

// TODO:class 实际上是函数, 是个语法糖
typeof People; // function
typeof Student; // function

// TODO:隐式原型和显示原型
console.log(xialuo.__proto__);
console.log(Student.prototype);
console.log(xialuo.__proto__ === Student.prototype);
// 每个 class 都有显示原型 prototype
// 每个实例都有隐式原型 __proto__
// 实例的 __proto__ 指向对应的 class 的 prototype 
// 获取属性 xialuo.name 或 执行方法 xialuo.sayHi()时, 先在自身属性和方法找, 找不到则自动去__proto__中找

// TODO:原型链: 函数原型通过继承关系联系在一起，形成的链式结构就被叫做原型链
console.log(Student.prototype.__proto__);
console.log(People.prototype);
console.log(People.prototype === Student.prototype.__proto__);
// 理解: xialuo 是 Student new 出来的, 则 xialuo 的 __proto__ 指向 Student 的 prototype
// Function.prototype / People.prototype 是 Object new 出来的, 则 People.prototype 的 __proto__ ...
// Object / Function / People 是 Function new 出来的, 则 People 的 __proto__ ...

// TODO: hasOwnProperty 判断是否是实例自己的属性
xialuo.hasOwnProperty('name'); // true
xialuo.hasOwnProperty('sayHi'); // false

// TODO: instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
      // TODO: 如何准确判断一个变量是不是数组?
      // a instanceof Array


// TODO:总结: https://segmentfault.com/a/1190000021232132


// TODO: inherits 函数
// es6 extends 被 babel 编译后, _inherits 方法里, subClass.__proto__ = superClass
// subClass.prototype 通过 Object.create 创建, 则 subClass.prototype.__proto__ 为 superClass.prototype
function _inherits(subClass, superClass) {
    subClass.prototype = Object.create(superClass.prototype, {
        constructor: {
            value: subClass, writable: true, configurable: true
        }
    });
    if (superClass) {
        _setPrototypeOf(subClass, superClass);
    }
}

function _setPrototypeOf(subClass, superClass) {
    subClass.__proto__ = superClass;
    return subClass;
}
</script>
</body>
</html>